안드로이드(Android) - 권한 획득 :: 안드로이드 설치 및 개발[SSISO Community]
 
SSISO 카페 SSISO Source SSISO 구직 SSISO 쇼핑몰 SSISO 맛집
추천검색어 : JUnit   Log4j   ajax   spring   struts   struts-config.xml   Synchronized   책정보   Ajax 마스터하기   우측부분

안드로이드 설치 및 개발
[1]
등록일:2018-07-15 08:24:35 (0%)
작성자:
제목:안드로이드(Android) - 권한 획득

프로젝트 생성

안드로이드 내에서 권한을 획득해보겠습니다.

암묵적 인텐트 중에 ACTION_CALL은 전화를 거는 권한이 없어서 수행할 수 없었습니다.

이번엔 권한을 획득하고 전화를 걸어보겠습니다.

Call App 이라는 이름으로 프로젝트를 생성해보겠습니다.



권한을 얻기 위한 준비

마시멜로우(Marshmallow) 이전 버전

1. AndroidMenifest.xml에 <uses-permission /> 을 작성해줘야한다.


마시멜로우(Marshmallow) 버전

1. AndroidMenifest.xml에 <uses-permission /> 을 작성해줘야한다.

2. 실시간으로 권한을 허가하는 작업이 필요하다.


필요 로직

버전이 마시멜로우인지 확인한다.

마시멜로우가 맞다면, 이 전에 권한에 대한 허가를 한 적이 있는지 확인한다.

허가한 적이 있으면 작업을 수행한다.

허가한 적이 없으면 거부한 적이 있는지 확인한다.

거부한적이 있으면 사용할수 있는 권한이 무엇인지 개발자에게 알려주고 사용할지 물어본다.

거부한적이 없으면 권한을 요청한다.


버튼 만들기

ACTION_CALL을 하기 위한 버튼을 만듭니다.





Button
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="전화 걸기"
    android:id="@+id/button"
    android:layout_below="@+id/textView"
    android:layout_alignParentLeft="true"
    android:layout_alignParentStart="true" />



ACTION_CALL 버튼을 MainActivity에서 만든다.


public class MainActivity extends AppCompatActivity {

    private Button button;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        button = (Button) findViewById(R.id.button);

        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {

                Intent intent = new Intent(Intent.ACTION_CALL, Uri.parse("tel:010-1111-2222"));
                startActivity(intent);
            }
        });
    }
}




권한 주기

Manifest.xml에 permission을 추가합니다.

<uses-permission android:name="android.permission.CALL_PHONE" />



로직 작성


public class MainActivity extends AppCompatActivity {

    private Button button;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        button = (Button) findViewById(R.id.button);

        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {

                // 사용자의 OS 버전이 마시멜로우 이상인지 체크한다.
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {

                    /**
                     * 사용자 단말기의 권한 중 "전화걸기" 권한이 허용되어 있는지 확인한다.
                     * Android는 C언어 기반으로 만들어졌기 때문에 Boolean 타입보다 Int 타입을 사용한다.
                     */
                    int permissionResult = checkSelfPermission(Manifest.permission.CALL_PHONE);

                    /**
                     * 패키지는 안드로이드 어플리케이션의 아이디이다.
                     * 현재 어플리케이션이 CALL_PHONE에 대해 거부되어있는지 확인한다.
                     */
                    if (permissionResult == PackageManager.PERMISSION_DENIED) {

                        /**
                         * 사용자가 CALL_PHONE 권한을 거부한 적이 있는지 확인한다.
                         * 거부한적이 있으면 True를 리턴하고
                         * 거부한적이 없으면 False를 리턴한다.
                         */
                        if (shouldShowRequestPermissionRationale(Manifest.permission.CALL_PHONE)) {
                            AlertDialog.Builder dialog = new AlertDialog.Builder(MainActivity.this);
                            dialog.setTitle("권한이 필요합니다.")
                                    .setMessage("이 기능을 사용하기 위해서는 단말기의 \"전화걸기\" 권한이 필요합니다. 계속 하시겠습니까?")
                                    .setPositiveButton("네", new DialogInterface.OnClickListener() {
                                        @Override
                                        public void onClick(DialogInterface dialog, int which) {

                                            /**
                                             * 새로운 인스턴스(onClickListener)를 생성했기 때문에
                                             * 버전체크를 다시 해준다.
                                             */
                                            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
                                                // CALL_PHONE 권한을 Android OS에 요청한다.
                                                requestPermissions(new String[]{Manifest.permission.CALL_PHONE}, 1000);
                                            }
                                        }
                                    })
                                    .setNegativeButton("아니요", new DialogInterface.OnClickListener() {
                                        @Override
                                        public void onClick(DialogInterface dialog, int which) {
                                            Toast.makeText(MainActivity.this, "기능을 취소했습니다", Toast.LENGTH_SHORT).show();
                                        }
                                    })
                                    .create()
                                    .show();
                        }
                        // 최초로 권한을 요청할 때
                        else {
                            // CALL_PHONE 권한을 Android OS에 요청한다.
                            requestPermissions(new String[]{Manifest.permission.CALL_PHONE}, 1000);
                        }
                    }
                    // CALL_PHONE의 권한이 있을 때
                    else {
                        // 즉시 실행
                        Intent intent = new Intent(Intent.ACTION_CALL, Uri.parse("tel:010-1111-2222"));
                        startActivity(intent);
                    }
                }
                // 마시멜로우 미만의 버전일 때
                else {
                    // 즉시 실행
                    Intent intent = new Intent(Intent.ACTION_CALL, Uri.parse("tel:010-1111-2222"));
                    startActivity(intent);
                }
            }
        });
    }

    /**
     * 권한 요청에 대한 응답을 이곳에서 가져온다.
     *
     * @param requestCode 요청코드
     * @param permissions 사용자가 요청한 권한들
     * @param grantResults 권한에 대한 응답들(인덱스별로 매칭)
     */
    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {

        if (requestCode == 1000) {

            // 요청한 권한을 사용자가 "허용" 했다면...
            if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                Intent intent = new Intent(Intent.ACTION_CALL, Uri.parse("tel:010-1111-2222"));

                // Add Check Permission
                if (ActivityCompat.checkSelfPermission(this, Manifest.permission.CALL_PHONE) != PackageManager.PERMISSION_GRANTED) {
                    startActivity(intent);
                }
            } else {
                Toast.makeText(MainActivity.this, "권한요청을 거부했습니다.", Toast.LENGTH_SHORT).show();
            }

        }
    }
}


안드로이드는 패키지를 아이디로 갖는다.



실행 하기

전화걸기 버튼을 눌러보겠습니다.


권한에 대한 요청이 나타납니다.

DENY 해보겠습니다.


거부한 뒤 다시 버튼을 누르면 이미 거부되어 있기 때문에

권한이 왜 필요한지 설명해줍니다.


권한이 왜 필요한지 확인 한 뒤 "네"를 누르면

다시 권한요청이 나타납니다.

[ALLOW]를 눌러 권한을 허락합니다.


권한을 허락했더니 이제 전화가 걸립니다!


클래스로 따로 만들기

PermissionRequester.java 클래스를 만들어 보겠습니다.


package com.ktds.cocomo.callapp;

import android.app.Activity;
import android.content.DialogInterface;
import android.content.pm.PackageManager;
import android.os.Build;
import android.support.v4.content.ContextCompat;
import android.support.v7.app.AlertDialog;

/**
 * Created by Minchang Jang on 2016-06-12.
 */
public class PermissionRequester {

    /**
     * 요청 AndroidOS의 버젼이 마쉬멜로우 이상 버젼이 아닐 경우
     */
    public static final int NOT_SUPPORT_VERSION = 2;

    /**
     * 요청 권한을 이미 가지고 있을 경우
     */
    public static final int ALREADY_GRANTED = -1;

    /**
     * 권한을 System에게 요청한 경우
     * Activity의 onRequestPermissionsResult() 로 결과 리턴됨.
     */
    public static final int REQUEST_PERMISSION = 0;

    private Activity context;
    private Builder builder;

    private void setBuilder(Builder builder) {
        this.builder = builder;
    }

    private PermissionRequester(Activity context) {
        this.context = context;
    }

    public int request(final String permission, final int requestCode, final OnClickDenyButtonListener denyAction) {

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            /*
             * 해당 App이 특정 권한을 가지고 있는지 검사함.
             * 리턴결과는 PackageManager.PERMISSION_DENIED 와 PackageManager.PERMISSION_GRANTED로 나눠짐.
             * PackageManager.PERMISSION_DENIED : 권한이 없음
               * PackageManager.PERMISSION_GRANTED : 권한이 있음.
             */
            int permissionCheck = ContextCompat.checkSelfPermission(context, permission);

            /*
             * 해당 권한이 없을 경우 처리 방법
              */
            if (permissionCheck == PackageManager.PERMISSION_DENIED) {

                /*
                 * 권한을 취득할 때 사용자로부터 확인을 받아야 하는지 확인
                 * 여기서 true가 나올 경우는 해당 앱에서 한번이라도 권한을 Deny한 경우일 때 말고는 없음.
                 * 권한에 대해서 허가하지 않은 경우 다시 한번 권한의 취득을 위해 사용자에게 이유를 고지해야 함.
                 * Mashmellow 버젼 이상부터 사용가능함.
                 */
                if (context.shouldShowRequestPermissionRationale(permission)) {

                    /*
                     * 권한 취득해야 하는 이유를 Dialog 등을 통해서 알린다.
                     */
                    AlertDialog.Builder dialog = new AlertDialog.Builder(context);
                    dialog.setTitle(builder.getTitle())
                            .setMessage(builder.getMessage())
                            .setPositiveButton(builder.getPositiveButtonName(), new DialogInterface.OnClickListener() {
                                @Override
                                public void onClick(DialogInterface dialog, int which) {
                                    /*
                                     * 권한의 취득을 요청한다.
                                     * 취득하고자 하는 권한을 배열에 넣고 요청한다.
                                     * 뒤에 들어가는 파라미터(requestCode)는 onRequestPermissionsResult() 에서 권한 취득 결과에서 사용된다.
                                     * startActiviryForResult의 Request Code와 유사함.
                                     */
                                    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
                                        context.requestPermissions(new String[]{permission}, requestCode);
                                    }
                                }
                            })
                            .setNegativeButton(builder.getNegativeButtonName(), new DialogInterface.OnClickListener() {
                                @Override
                                public void onClick(DialogInterface dialog, int which) {
                                    denyAction.onClick(context);
                                }
                            }).create().show();

                    return REQUEST_PERMISSION;
                } else {
                    /*
                     * 권한의 취득 요청을 처음 할 때
                        * 권한의 취득을 요청한다.
                     * 취득하고자 하는 권한을 배열에 넣고 요청한다.
                     * 뒤에 들어가는 파라미터(1000)는 onRequestPermissionsResult() 에서 권한 취득 결과에서 사용된다.
                     * startActiviryForResult의 Request Code와 유사함.
                     */
                    context.requestPermissions(new String[]{permission}, requestCode);
                    return REQUEST_PERMISSION;
                }

            } else {
                /*
                 * 이미 권한을 가지고 있을 경우
                    * 해야할 일을 수행한다.
                 */
                return ALREADY_GRANTED;
            }

        }

        return NOT_SUPPORT_VERSION;
    }

    public static class Builder {

        private PermissionRequester requester;

        public Builder(Activity context) {
            requester = new PermissionRequester(context);
        }

        private String title = "권한 요청";
        private String message = "기능의 사용을 위해 권한이 필요합니다.";
        private String positiveButtonName = "네";
        private String negativeButtonName = "아니요";

        public String getTitle() {
            return title;
        }

        public Builder setTitle(String title) {
            this.title = title;
            return this;
        }

        public String getMessage() {
            return message;
        }

        public Builder setMessage(String message) {
            this.message = message;
            return this;
        }

        public String getPositiveButtonName() {
            return positiveButtonName;
        }

        public Builder setPositiveButtonName(String positiveButtonName) {
            this.positiveButtonName = positiveButtonName;
            return this;
        }

        public String getNegativeButtonName() {
            return negativeButtonName;
        }

        public Builder setNegativeButtonName(String negativeButtonName) {
            this.negativeButtonName = negativeButtonName;
            return this;
        }

        public PermissionRequester create() {
            this.requester.setBuilder(this);
            return this.requester;
        }

    }

    public interface OnClickDenyButtonListener {

        public void onClick(Activity activity);

    }

}


만든 클래스를 이용해 권한을 요청해보겠습니다.


package com.ktds.cocomo.callapp;

import android.Manifest;
import android.app.Activity;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.net.Uri;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.v4.app.ActivityCompat;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;

public class MainActivity extends AppCompatActivity {

    private Button button;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        button = (Button) findViewById(R.id.button);

        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {

                int result = new PermissionRequester.Builder(MainActivity.this)
                        .setTitle("권한 요청")
                        .setMessage("권한을 요청합니다.")
                        .setPositiveButtonName("네")
                        .setNegativeButtonName("아니요.")
                        .create()
                        .request(Manifest.permission.CALL_PHONE, 1000, new PermissionRequester.OnClickDenyButtonListener() {
                            @Override
                            public void onClick(Activity activity) {
                                Log.d("xxx", "취소함.");
                            }
                        });

                if (result == PermissionRequester.ALREADY_GRANTED) {
                    Log.d("RESULT", "권한이 이미 존재함.");
                    if (ActivityCompat.checkSelfPermission(MainActivity.this, Manifest.permission.CALL_PHONE) == PackageManager.PERMISSION_GRANTED) {
                        Intent intent = new Intent(Intent.ACTION_CALL, Uri.parse("tel:010-1111-1111"));
                        startActivity(intent);
                    }
                } else if (result == PermissionRequester.NOT_SUPPORT_VERSION) {
                    Log.d("RESULT", "마쉬멜로우 이상 버젼 아님.");
                    Intent intent = new Intent(Intent.ACTION_CALL, Uri.parse("tel:010-1111-1111"));
                    startActivity(intent);
                } else if (result == PermissionRequester.REQUEST_PERMISSION) {
                    Log.d("RESULT", "요청함. 응답을 기다림.");
                    Intent intent = new Intent(Intent.ACTION_CALL, Uri.parse("tel:010-1111-1111"));
                    startActivity(intent);
                }
                
            }
        });
    }

    /**
     * 권한 요청에 대한 응답을 이곳에서 가져온다.
     *
     * @param requestCode  요청코드
     * @param permissions  사용자가 요청한 권한들
     * @param grantResults 권한에 대한 응답들(인덱스별로 매칭)
     */
    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {

        if (requestCode == 1000) {

            // 요청한 권한을 사용자가 "허용" 했다면...
            if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                Intent intent = new Intent(Intent.ACTION_CALL, Uri.parse("tel:010-1111-2222"));

                // Add Check Permission
                if (ActivityCompat.checkSelfPermission(this, Manifest.permission.CALL_PHONE) == PackageManager.PERMISSION_GRANTED) {
                    startActivity(intent);
                }
            } else {
                Toast.makeText(MainActivity.this, "권한요청을 거부했습니다.", Toast.LENGTH_SHORT).show();
            }

        }
    }
}



출처: http://cocomo.tistory.com/393?category=687308 [Cocomo Coding]
[본문링크] 안드로이드(Android) - 권한 획득
[1]
코멘트(이글의 트랙백 주소:/cafe/tb_receive.php?no=34705
작성자
비밀번호

 

SSISOCommunity

[이전]

Copyright byCopyright ⓒ2005, SSISO Community All Rights Reserved.